import aiohttp
import hashlib
import time
from datetime import datetime, timedelta
from typing import Optional, Dict
from loguru import logger
from app.core.platform_config import platform_config
from app.utils.logger import log_exception
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA

class PlatformAuth:
    def __init__(self):
        self.session = None
        
    async def initialize(self):
        """初始化HTTP会话"""
        if not self.session:
            self.session = aiohttp.ClientSession()
            
    async def close(self):
        """关闭HTTP会话"""
        if self.session:
            await self.session.close()
            self.session = None
            
    @log_exception
    async def get_dahua_token(self, force_refresh: bool = False) -> Optional[str]:
        """获取大华平台的访问令牌"""
        config = platform_config.dahua
        logger.debug(f"大华平台配置: api_host={config.api_host}, app_key={config.app_key}")
        
        # 检查令牌是否有效
        if not force_refresh and config.access_token and config.token_expires_at:
            if config.token_expires_at > datetime.now() + timedelta(minutes=5):
                logger.debug(f"使用现有token: {config.access_token}")
                logger.debug(f"token过期时间: {config.token_expires_at}")
                return config.access_token
                
        try:
            # 确保session已初始化
            if not self.session:
                logger.debug("初始化HTTP会话")
                await self.initialize()
                
            # 获取public_key
            pubkey = ''
            async with self.session.get(f"{config.api_host}{config.public_key}") as response:
                response_text = await response.text()
                logger.debug(f"大华平台public_key响应内容: {response_text}")
                
                if response.status == 200:
                    try:
                        result = await response.json()
                        logger.debug(f"解析响应JSON: {result}")

                        pubkeyDate = result.get("data")
                        pubkey =  pubkeyDate.get('publicKey')
                        
                    except Exception as e:
                        logger.error(f"解析大华平台响应JSON失败: {str(e)}")
                            

            password = password.encode()
            pub_key = """-----BEGIN PUBLIC KEY-----
                """ + pubkey.strip('"') + """
                -----END PUBLIC KEY-----"""
            key_obj = RSA.importKey(pub_key)
            cipher = PKCS1_v1_5.new(key_obj)
            web_safe_pwd = base64.b64encode(cipher.encrypt(config.password))
            
            # 构建请求数据
        
            data = {
                "grant_type": "password",
                "username": config.username,
                "password": web_safe_pwd.decode(),
                "client_id":config.client_id,
                "client_secret": config.client_secret,
                "public_key": pubkey
            }
            
            logger.debug(f"正在请求大华平台令牌，URL: {config.api_host}{config.auth_path}")
            logger.debug(f"请求数据: {data}")
            
            # 发送请求
            async with self.session.post(f"{config.api_host}{config.auth_path}", json=data) as response:
                logger.debug(f"大华平台响应状态码: {response.status}")
                response_text = await response.text()
                logger.debug(f"大华平台响应内容: {response_text}")
                
                if response.status == 200:
                    try:
                        result = await response.json()
                        logger.debug(f"解析响应JSON: {result}")
                        if result.get("code") == 0:
                            token_data = result.get("data", {})
                            config.access_token = token_data.get("accessToken")
                            expires_in = token_data.get("expiresIn", 7200)  # 默认2小时
                            config.token_expires_at = datetime.now() + timedelta(seconds=expires_in)
                            logger.info(f"成功获取大华平台令牌: {config.access_token}")
                            logger.debug(f"令牌过期时间: {config.token_expires_at}")
                            return config.access_token
                    except Exception as e:
                        logger.error(f"解析大华平台响应JSON失败: {str(e)}")
                        
                logger.error(f"获取大华平台令牌失败: {response_text}")
                return None
                
        except Exception as e:
            logger.error(f"获取大华平台令牌异常: {str(e)}")
            return None
            
    @log_exception
    async def get_hikvision_token(self, force_refresh: bool = False) -> Optional[str]:
        """获取海康平台的访问令牌"""
        config = platform_config.hikvision
        
        # 检查令牌是否有效
        if not force_refresh and config.access_token and config.token_expires_at:
            if config.token_expires_at > datetime.now() + timedelta(minutes=5):
                return config.access_token
                
        try:
            # 生成签名
            timestamp = str(int(time.time() * 1000))
            sign_str = f"{config.app_key}{timestamp}{config.app_secret}"
            sign = hashlib.sha256(sign_str.encode()).hexdigest()
            
            # 构建请求数据
            data = {
                "appKey": config.app_key,
                "timestamp": timestamp,
                "sign": sign
            }
            
            # 发送请求
            async with self.session.post(f"{config.api_host}{config.auth_path}", json=data) as response:
                if response.status == 200:
                    result = await response.json()
                    if result.get("code") == "0":
                        token_data = result.get("data", {})
                        config.access_token = token_data.get("accessToken")
                        expires_in = token_data.get("expireTime", 7200)  # 默认2小时
                        config.token_expires_at = datetime.now() + timedelta(seconds=expires_in)
                        return config.access_token
                        
                logger.error(f"获取海康平台令牌失败: {await response.text()}")
                return None
                
        except Exception as e:
            logger.error(f"获取海康平台令牌异常: {str(e)}")
            return None
            
    async def get_dahua_headers(self) -> Dict[str, str]:
        """获取大华平台请求头"""
        token = await self.get_dahua_token()
        logger.debug(f"获取到的token: {token}")
        
        if not token:
            logger.error("无法获取大华平台访问令牌")
            raise Exception("无法获取大华平台访问令牌")
            
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {token}"
        }
        logger.debug(f"生成的请求头: {headers}")
        return headers
        
    async def get_hikvision_headers(self) -> Dict[str, str]:
        """获取海康平台请求头"""
        token = await self.get_hikvision_token()
        if not token:
            raise Exception("无法获取海康平台访问令牌")
            
        return {
            "Content-Type": "application/json",
            "Access-Token": token
        }

# 创建全局认证服务实例
platform_auth = PlatformAuth() 